﻿#include "pch.h"

CStdInfManager::CStdInfManager()
{
    memset(this, 0, sizeof(CStdInfManager));
}

void CStdInfManager::printSelf(char *captionUpper, int32_t deep)
{
    char caption[1024];
    sprintf(caption, "%s:%s", captionUpper, "CStdInfManager");
    print4x(this, sizeof(CStdInfManager), caption);
    if (--deep >= 0)
    {
        if (this->pAmtInfWrapper)
        {
            this->pAmtInfWrapper->printSelf(caption, deep);
        }
        if (this->pCptInfWrapper)
        {
            this->pCptInfWrapper->printSelf(caption, deep);
        }
        if (this->pEParaWrapper)
        {
            this->pEParaWrapper->printSelf(caption, deep);
        }
        if (this->pIdtInfWrapper)
        {
            this->pIdtInfWrapper->printSelf(caption, deep);
        }
    }
}

// sub_10022FBF
CStdInfManager *CStdInfManager::init(CAmtInfWrapper *pAmtInfWrapper, CCptInfWrapper *pCptInfWrapper,
                                     CEParaWrapper *pEParaWrapper, CIdtInfWrapper *pIdtInfWrapper, int32_t curveType,
                                     int32_t oneOrZero)
{
    int32_t i;
    int32_t method;

    this->pAmtInfWrapper = pAmtInfWrapper;
    this->pCptInfWrapper = pCptInfWrapper;
    this->pEParaWrapper = pEParaWrapper;
    this->pIdtInfWrapper = pIdtInfWrapper;
    this->AmtInfNum = ((CBaseWrapper *)this->pAmtInfWrapper)->getNum();
    this->CptInfNum = ((CBaseWrapper *)this->pCptInfWrapper)->getNum();
    this->EParaNum = ((CBaseWrapper *)this->pIdtInfWrapper)->getNum();
    this->curveType = curveType;
    this->oneOrZero = oneOrZero;
    this->segCalibMode = 0;
    if (curveType == 3)
    {
        this->segCalibMode = 2;
    }
    else if (this->oneOrZero == 3)
    {
        this->oneOrZero = 0;
        this->segCalibMode = 1;
    }
    else
    {
        this->segCalibMode = 0;
    }
    this->amtMValue = (double *)new BYTE[8 * this->AmtInfNum];
    this->amtM2Value = (double *)new BYTE[8 * this->AmtInfNum];
    method = this->pEParaWrapper->getEparamMethod();
    for (i = 0; i < this->AmtInfNum; ++i)
    {
        this->amtMValue[i] = pAmtInfWrapper->getAmtMValue(i, method);
        if (this->amtMValue[i] < 1.0e-30)
        {
            this->amtMValue[i] = 100.0;
        }
        this->amtM2Value[i] = pAmtInfWrapper->getAmtM2Value(i);
        if (this->amtM2Value[i] < 1.0e-30)
        {
            this->amtM2Value[i] = 100.0;
        }
    }
    this->clear();
    return this;
};

// sub_1002318F
void CStdInfManager::clear()
{
    this->currentAmtIdx = 0;
    this->pAmtInfWrapper->clear();
};

// sub_1001D580
void *CStdInfManager::close(char flag)
{
    this->close();
    if (flag & 1)
    {
        delete this;
        return NULL;
    }
    return this;
};

// sub_1001D5B0
void CStdInfManager::close()
{
    delete[] this->amtMValue;
    delete[] this->amtM2Value;
};

// sub_1001AD70
int32_t CStdInfManager::isAmtIndexNotZero()
{
    return !this->currentAmtIdx && !this->getcurrentAmtRepIdx();
};

// sub_100231AE
int32_t CStdInfManager::cleanCPTItem()
{
    int32_t result = 0;
    TSTDCPTListItem *pCPT = (TSTDCPTListItem *)this->pCptInfWrapper->head;

    for (int32_t i = 0; i < this->CptInfNum; ++i)
    {
        pCPT[i].area = 0;
        pCPT[i].weight = 0;
        result = i + 1;
    }
    return result;
};

// sub_1001ADF0
int32_t CStdInfManager::isValidAmpRepIndex()
{
    return this->getcurrentAmtRepIdx() == this->getCurrentAmtRepNum() - 1;
};

// sub_100232DE
CStdInfManager *CStdInfManager::eliminateRepNumInCPT(int32_t eIdx)
{
    int32_t offs = this->EParaNum * this->currentAmtIdx;
    int32_t currentAmtRepNum;
    TSTDCPTListItem *pCPT = (TSTDCPTListItem *)this->pCptInfWrapper->head;
    currentAmtRepNum = this->getCurrentAmtRepNum();
    if (eIdx >= 0)
    {
        if (eIdx < this->EParaNum)
        {
            if (this->currentAmtIdx < this->AmtInfNum && currentAmtRepNum > 0)
            {
                pCPT[offs + eIdx].area = pCPT[offs + eIdx].area / this->getCurrentAmtRepNum();
                pCPT[offs + eIdx].height = pCPT[offs + eIdx].height / this->getCurrentAmtRepNum();
            }
        }
    }
    return this;
};

// sub_1001AE60
int32_t CStdInfManager::reachedLastAmtRepsNum()
{
    if (this->currentAmtIdx == this->AmtInfNum - 1)
    {
        if (this->getcurrentAmtRepIdx() == this->getCurrentAmtRepNum() - 1)
        {
            return true;
        }
    }
    return false;
};

// sub_1002395D
int32_t CStdInfManager::calcMethodValueAndWeightAll()
{
    int32_t amtNum;
    int32_t stdNo;
    int32_t isdtIdx;
    int32_t stdIdx;
    int32_t isdtNo;
    int32_t i;
    int32_t j;
    int32_t k;
    double *cptAreaOrWeight;
    double *amtMValue;
    double *arrWeight;
    double *arrValue;
    int32_t eMethod;
    int32_t stdNum;
    int32_t *stdnoArray = nullptr;

    if (this->oneOrZero)
    {
        amtNum = this->AmtInfNum + 1;
    }
    else
    {
        amtNum = this->AmtInfNum;
    }
    cptAreaOrWeight = NULL;
    amtMValue = NULL;
    eMethod = this->pEParaWrapper->getEparamMethod();
    if (!eMethod)
    {
        return false;
    }
    arrValue = new double[amtNum];
    arrWeight = new double[amtNum];
    if (!arrValue || !arrWeight)
    {
        delete[] arrValue;
        delete[] arrWeight;
        return false;
    }
    memset(arrValue, 0, sizeof(double) * amtNum);
    memset(arrWeight, 0, sizeof(double) * amtNum);
    if (eMethod == 2 || eMethod == 5)
    {
        stdNum = this->pIdtInfWrapper->fetchStdnoSelfArray(&stdnoArray);
        if (stdNum <= 0)
        {
            delete[] arrValue;
            delete[] arrWeight;
            return false;
        }
        cptAreaOrWeight = new double[stdNum * amtNum];
        amtMValue = new double[stdNum * amtNum];
        if (!cptAreaOrWeight || !amtMValue)
        {
            delete[] arrValue;
            delete[] arrWeight;
            delete[] cptAreaOrWeight;
            delete[] amtMValue;
            return false;
        }
        memset(cptAreaOrWeight, 0, sizeof(double) * stdNum * amtNum);
        memset(amtMValue, 0, sizeof(double) * stdNum * amtNum);
    }
    this->pIdtInfWrapper->clearCorrectFactor();
    if (eMethod == 2 || eMethod == 5)
    {
        for (i = 0; i < this->EParaNum; ++i)
        {
            if (this->pIdtInfWrapper->checkStdNo(i))
            {
                isdtNo = this->pIdtInfWrapper->getIsdtNoSelf(i);
                isdtIdx = qryIdxFromArray(isdtNo, stdNum, stdnoArray);
                if (isdtIdx >= 0)
                {
                    this->calcAllCptAreaAndAmtValue(i, &cptAreaOrWeight[amtNum * isdtIdx],
                                                    &amtMValue[amtNum * isdtIdx]);
                }
            }
        }
        for (j = 0; j < this->EParaNum; ++j)
        {
            if (this->pIdtInfWrapper->checkStdNo(j))
            {
                this->pIdtInfWrapper->setCorrectFactor(j, 1.0, 0.0, 1.0, 0.0, 0.0);
            }
            else if (this->pIdtInfWrapper->isStdnoUsed(j))
            {
                stdNo = this->pIdtInfWrapper->getStdnoUsed(j);
                stdIdx = qryIdxFromArray(stdNo, stdNum, stdnoArray);
                this->setAreaAndWeightFromCPT(j, &cptAreaOrWeight[amtNum * stdIdx], &amtMValue[amtNum * stdIdx],
                                              arrValue, arrWeight);
                this->calcSegCalibGetDbl5(j, arrValue, arrWeight, amtNum);
            }
        }
    }
    else
    {
        for (k = 0; k < this->EParaNum; ++k)
        {
            this->calcCPTValueAndWeightArray(k, arrValue, arrWeight);
            this->calcSegCalibGetDbl5(k, arrValue, arrWeight, amtNum);
        }
    }
    delete[] arrValue;
    delete[] arrWeight;
    if (eMethod == 2 || eMethod == 5)
    {
        delete[] cptAreaOrWeight;
        delete[] amtMValue;
    }
    return true;
};

// sub_100233DD
CStdInfManager *CStdInfManager::incCurrentAmtIdx()
{
    this->incCurrentAmtRepIndex();
    if (this->getcurrentAmtRepIdx() == this->getCurrentAmtRepNum())
    {
        this->clearCurrentAmtRepIndex();
        ++this->currentAmtIdx;
        if (this->currentAmtIdx == this->AmtInfNum)
        {
            this->currentAmtIdx = 0;
        }
    }
    return this;
};

// sub_1001ADB0
int32_t CStdInfManager::getcurrentAmtRepIdx()
{
    return this->pAmtInfWrapper->getRepIndex(this->currentAmtIdx);
};

// sub_1001AE20
int32_t CStdInfManager::getCurrentAmtRepNum()
{
    return this->getAmtRepNum(this->currentAmtIdx);
};

// sub_1001AE40
int32_t CStdInfManager::getAmtRepNum(int32_t amtIdx)
{
    TSTDAMTListItem *pAmt = (TSTDAMTListItem *)this->pAmtInfWrapper->head; // x0 -> 0
    return pAmt[amtIdx].repNum;
};

// sub_100235BF
int32_t CStdInfManager::calcAllCptAreaAndAmtValue(int32_t amtIdx, double *cptAreaOrWeight, double *amtMValue)
{
    int32_t i;
    int32_t oneOrZero;

    oneOrZero = this->oneOrZero != 0 ? 1 : 0;
    for (i = 0; i < this->AmtInfNum; ++i)
    {
        cptAreaOrWeight[i + oneOrZero] = this->getCptAreaOrHeight(i, amtIdx);
        amtMValue[i + oneOrZero] = this->getWeightedAmtM2Value(i, amtIdx);
    }
    return true;
};

// sub_1002363F
int32_t CStdInfManager::setAreaAndWeightFromCPT(int32_t idx, double *cptAreaOrWeight, double *amtMValue,
                                                double *arrValue, double *arrWeight)
{
    int32_t i;
    int32_t oneOrZero;

    oneOrZero = this->oneOrZero != 0 ? 1 : 0;
    for (i = 0; i < this->AmtInfNum; ++i)
    {
        if (cptAreaOrWeight[i + oneOrZero] > 0.0 && amtMValue[i + oneOrZero] > 0.0)
        {
            arrValue[i + oneOrZero] = this->getCptAreaOrHeight(i, idx);
            arrWeight[i + oneOrZero] = this->getCptWeight(i, idx);
            arrValue[i + oneOrZero] = arrValue[i + oneOrZero] / cptAreaOrWeight[i + oneOrZero];
            arrWeight[i + oneOrZero] = arrWeight[i + oneOrZero] / amtMValue[i + oneOrZero];
        }
        else
        {
            arrValue[i + oneOrZero] = 0;
            arrWeight[i + oneOrZero] = 0;
        }
    }
    return true;
};

// sub_10023D6D
double *CStdInfManager::calcSegCalibGetDbl5(int32_t eIdx, double *arrValue, double *arrWeight, int32_t amtNum)
{
    int32_t curveType;
    double *d5;
    int32_t oneOrZero;
    int32_t sortedAmtNum;

    oneOrZero = this->oneOrZero != 0 ? 1 : 0;
    sortedAmtNum = sortAreaAndWeight(arrValue, arrWeight, amtNum, oneOrZero);
    curveType = this->curveType + 1;
    if (this->segCalibMode == 1)
    {
        d5 = calcDblFiveM1(arrValue, arrWeight, sortedAmtNum, oneOrZero, curveType);
    }
    else
    {
        d5 = calcDblFive(arrValue, arrWeight, sortedAmtNum, oneOrZero, curveType, this->oneOrZero);
    }
    this->pIdtInfWrapper->setCorrectFactor(eIdx, d5[4], *d5, d5[1], d5[2], d5[3]);
    this->pIdtInfWrapper->calcSegCalibItem(eIdx, sortedAmtNum - oneOrZero, &arrValue[oneOrZero],
                                           &arrWeight[oneOrZero], this->segCalibMode,
                                           ((TEPara *)(this->pEParaWrapper->head))->quantBy);
    return d5;
};

// sub_10024F00
int32_t CStdInfManager::incCurrentAmtRepIndex()
{
    ++this->pAmtInfWrapper->repIndexes[this->currentAmtIdx];
    return this->currentAmtIdx;
};

// sub_10024F30
int32_t CStdInfManager::clearCurrentAmtRepIndex()
{
    this->pAmtInfWrapper->repIndexes[this->currentAmtIdx] = 0;
    return this->currentAmtIdx;
};

// sub_10023795
int32_t CStdInfManager::calcCPTValueAndWeightArray(int32_t eIdx, double *arrValue, double *arrWeight)
{
    int32_t i;
    int32_t oneOrZero;
    int32_t eMethod;

    oneOrZero = this->oneOrZero != 0 ? 1 : 0;
    eMethod = this->pEParaWrapper->getEparamMethod();
    for (i = 0; i < this->AmtInfNum; ++i)
    {
        arrValue[i + oneOrZero] = this->getCptAreaOrHeight(i, eIdx);
        arrWeight[i + oneOrZero] = this->getCptWeight(i, eIdx);
        if (arrValue[i + oneOrZero] > 0.0 && arrWeight[i + oneOrZero] > 0.0)
        {
            if (eMethod == 1)
            {
                if (this->amtMValue[i] == 0.0)
                {
                    arrValue[i + oneOrZero] = 0;
                    arrWeight[i + oneOrZero] = 0;
                }
            }
            else if (eMethod == 4)
            {
                arrValue[i + oneOrZero] = log(arrValue[i + oneOrZero]);
                arrWeight[i + oneOrZero] = log(arrWeight[i + oneOrZero]);
            }
        }
        else
        {
            arrValue[i + oneOrZero] = 0;
            arrWeight[i + oneOrZero] = 0;
        }
    }
    return true;
};

// sub_10023437
double CStdInfManager::getCptAreaOrHeight(int32_t amtIdx, int32_t eIdx)
{
    double v4;
    int32_t basedOnArea;
    TSTDCPTListItem *pCPT = (TSTDCPTListItem *)this->pCptInfWrapper->head;
    basedOnArea = this->pIdtInfWrapper->isBaseOnArea(eIdx, ((TEPara *)(this->pEParaWrapper->head))->based);
    if (amtIdx >= this->AmtInfNum || eIdx >= this->EParaNum)
    {
        return 0.0;
    }
    if (basedOnArea)
    {
        v4 = pCPT[this->EParaNum * amtIdx + eIdx].area;
    }
    else
    {
        v4 = pCPT[this->EParaNum * amtIdx + eIdx].height;
    }
    return v4;
};

// sub_100234DB
double CStdInfManager::getCptWeight(int32_t amtIdx, int32_t eIdx)
{
    TSTDCPTListItem *pCPT = (TSTDCPTListItem *)this->pCptInfWrapper->head;
    if (amtIdx >= this->AmtInfNum || eIdx >= this->EParaNum)
    {
        return 0.0;
    }
    if (this->pEParaWrapper->getEparamMethod() == 1)
    {
        return pCPT[this->EParaNum * amtIdx + eIdx].weight;
    }
    return this->amtMValue[amtIdx] * pCPT[this->EParaNum * amtIdx + eIdx].weight;
};

// sub_10023566
double CStdInfManager::getWeightedAmtM2Value(int32_t amtIdx, int32_t eIdx)
{
    double result;
    TSTDCPTListItem *pCPT = (TSTDCPTListItem *)this->pCptInfWrapper->head;

    if (amtIdx >= this->AmtInfNum || eIdx >= this->EParaNum)
    {
        result = 0.0;
    }
    else
    {
        result = this->amtM2Value[amtIdx] * pCPT[this->EParaNum * amtIdx + eIdx].weight;
    }
    return result;
};

// sub_1002320E
CStdInfManager *CStdInfManager::addCptAreaAndWeight(int32_t idx, double area, float weight)
{
    if (idx >= 0)
    {
        if (idx < this->EParaNum)
        {
            if (this->currentAmtIdx < this->AmtInfNum)
            {
                TSTDCPTListItem *pCPT = (TSTDCPTListItem *)this->pCptInfWrapper->head;
                pCPT[this->EParaNum * this->currentAmtIdx + idx].area += area;
                pCPT[this->EParaNum * this->currentAmtIdx + idx].weight += weight;
            }
        }
    }
    return this;
};
